import {IElement} from '@antv/g-base/src/interfaces';
import {G6GraphEvent, Graph, INode, IPoint, IShape} from '@antv/g6';
import NodeType from "../consts/node-type";
import NodeAttrField from "../consts/node-attr-field";
import GraphKeyName from "../consts/graph-key-name";
import CommonUtil from "./common-util";

export default class G6Util {

    /**
     * 生成节点id
     * @param type
     * @param len
     */
    static generateNodeId(type: string = 'user-task', len: number = 4): string {
        let prefixStr = 'UT';
        switch (type) {
            case NodeType.START_EVENT: {
                prefixStr = 'SE';
                break;
            }
            case 'direct-polyline': {
                prefixStr = 'DL';
                break;
            }
        }

        return `${prefixStr}${CommonUtil.randomNumeric(len)}`;
    }

    /**
     * 来源是锚点
     * @param event
     */
    static isAnchor(event: G6GraphEvent) {
        return event.target.attr(NodeAttrField.ANCHOR_IS_ANCHOR);
    }

    // static highlightOtherNodesAnchors(nodes: INode[]) {
    //     nodes.forEach((node: INode) => {
    //         node.getContainer().getChildren().forEach(child => {
    //             if (child.attr(NodeAttrField.ANCHOR_IS_ANCHOR)) {
    //                 child.attr({
    //                     fill: '#e1f5fe',
    //                     stroke: '#81d4fa',
    //                     lineWidth: 6,
    //                     r: 8,
    //                     opacity: .9,
    //                 });
    //             }
    //         });
    //     });
    // }
    //
    // static removeOtherNodesSelectBox(nodes: INode[]) {
    //     nodes.forEach((node: INode) => {
    //         const group = node.getContainer();
    //         group.getChildren().forEach(child => {
    //             if (child.attr(NodeAttrField.SELECTBOX_IS_SELECTBOX)) {
    //                 group.removeChild(child);
    //             }
    //         });
    //     });
    // }
    //
    // static findGhostNodes(graph: Graph) {
    //     const ghostNodes = graph.findAll('node', (node: INode) => {
    //         return /^ghost-/.test(node.getModel().id as string);
    //     });
    //     if (ghostNodes) {
    //         for (let i = ghostNodes.length - 1; i >= 0; i--) {
    //             const ghostNode = ghostNodes[i];
    //             graph.removeItem(ghostNode);
    //         }
    //     }
    // }

    static removeDragGhostNodes(graph: Graph) {
        // const ghostNodes = graph.findAll('node', (node: INode) => /^ghost-/.test(node.getModel().id as string));
        const dragNodeIds = graph.get(GraphKeyName.DRAG_NODE_IDS);
        if (dragNodeIds && dragNodeIds.length) {
            dragNodeIds.forEach((dragNodeId: string) => {
                const targetNode = graph.findById(dragNodeId);
                // const nodeType = targetNode.getModel().type;
                // const item = (event as unknown as G6GraphEvent).item as INode;
                const model = targetNode.getModel();
                const ghostId = `ghost-${model.id}`;
                const ghostNode = graph.findById(ghostId);
                graph.removeItem(ghostNode, false);
            });
        }
    }

    /**
     * 最近的锚点
     *
     * @param node
     * @param point
     */
    static getNearestAnchor(node: INode, point: {x: number, y: number}) {
        const anchors = node.getAnchorPoints() as IPoint[];

        let min = 999999999;
        let index = 9;
        let nearestAnchor = null;
        for (const anchor of anchors) {
            const distance = Math.pow(anchor.x - point.x, 2) + Math.pow(anchor.y - point.y, 2);
            if (distance < min) {
                index = anchor.anchorIndex as number;
                min = distance;
                nearestAnchor = anchor;
            }
        }

        return nearestAnchor;
    }

    /**
     * 给定的点，是否在节点范围内，根据bbox以及
     * @param node
     * @param point
     */
    static inNodeArea(node: INode, point: {x: number, y: number}): boolean {

        const {x, y} = point;

        {
            const bbox = node.getBBox();
            const {minX, minY, maxX, maxY} = bbox;
            if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
                return true;
            }
        }

        const anchorElements = node.getContainer().getChildren().filter((child: IElement) => child.attr(NodeAttrField.ANCHOR_IS_ANCHOR));
        for (const i in anchorElements) {
            if (i) {
                const anchorElement = anchorElements[i];

                const r = anchorElement.attr('r') as number;
                const anchor = node.getAnchorPoints()[i] as IPoint;
                const distance = Math.sqrt(Math.pow(x - anchor.x, 2) + Math.pow(y - anchor.y, 2));
                if (r >= distance) {
                    return true;
                }
            }
        }

        return false;
    }
}
